package com.napenalki.toto.service.impl;

import static com.napenalki.toto.service.impl.EntityValidationHelper.*;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.napenalki.toto.dao.MatchDao;
import com.napenalki.toto.dao.SpecialEventDao;
import com.napenalki.toto.domain.Event;
import com.napenalki.toto.domain.Match;
import com.napenalki.toto.domain.SpecialEvent;
import com.napenalki.toto.domain.SpecialEvents;
import com.napenalki.toto.domain.Stages;
import com.napenalki.toto.service.EventService;
import com.napenalki.toto.service.IllegalEntryException;

@Service
public class EventServiceImpl implements EventService {

    private SpecialEventDao specialEventDao;
    private MatchDao matchDao;

    @Autowired
    public EventServiceImpl(SpecialEventDao specialEventsDao, MatchDao matchDao) {
        this.specialEventDao = specialEventsDao;
        this.matchDao = matchDao;
    }

    @Override
    public SpecialEvent addSpecialEvent(SpecialEvent event) {

        validateEntity(event);

        SpecialEvent eventx = specialEventDao.findSpecialEventByType(event
                .getEventType());

        if (eventx == null) {
            specialEventDao.addSpecialEvent(event);
            return event;
        }

        return eventx;
    }

    @Override
    public Match addMatch(Match match) {

        validateEntity(match);

        Match matchx = matchDao.findMatchByTeamsAndStage(match.getTeam1Name(),
                match.getTeam2Name(), match.getStage());

        if (matchx == null) {
            matchDao.addMatch(match);
            return match;
        }

        return matchx;
    }

    @Override
    public SpecialEvent findSpecialEvendById(int eventId) {
        return specialEventDao.findSpecialEventById(eventId);
    }

    @Override
    public Match findMatchById(int matchId) {
        return matchDao.findMatchById(matchId);
    }

    @Override
    public List<SpecialEvent> findAllSpecialEvents() {
        return specialEventDao.findAllSpecialEvents();
    }

    @Override
    public List<Match> findAllMatches() {
        return matchDao.findAllMatches();
    }

    @Override
    public List<Match> findMatchesByTeam(String teamName) {
        if (teamName == null) {
            throw new IllegalEntryException("Team name should not be null");
        }
        return matchDao.findMatchesByTeam(teamName);
    }

    @Override
    public List<Match> findCompletedGroupStageMatchesByTeam(String teamName) {
        List<Match> allMatches = findMatchesByTeam(teamName);
        List<Match> completedGroupMatches = new ArrayList<Match>(allMatches
                .size());

        for (int i = 0; i < allMatches.size(); i++) {
            Match current = allMatches.get(i);

            if (current.getResult() != null && isInGroupStage(current)) {
                completedGroupMatches.add(current);
            }
        }

        return completedGroupMatches;
    }

    private boolean isInGroupStage(Match match) {
        return match.getStage().toString().toLowerCase().startsWith("group");
    }

    @Override
    public SpecialEvent findSpecialEventByType(SpecialEvents eventType) {
        if (eventType == null) {
            throw new IllegalEntryException("Special event type cannot be null");
        }

        return specialEventDao.findSpecialEventByType(eventType);
    }

    @Override
    public List<Match> findMatchesByStage(Stages stage) {
        if (stage == null) {
            throw new IllegalEntryException("Stage cannot be null");
        }
        return matchDao.findMatchesByStage(stage);
    }

    @Override
    public Match findMatchByTeamsAndStage(String team1Name, String team2Name,
            Stages stage) {
        if (team1Name == null) {
            throw new IllegalEntryException("Team 1 should not be null");
        }
        if (team2Name == null) {
            throw new IllegalEntryException("Team 2 should not be null");
        }
        if (stage == null) {
            throw new IllegalEntryException("Stage should not be null");
        }

        return matchDao.findMatchByTeamsAndStage(team1Name, team2Name, stage);
    }

    @Override
    public List<SpecialEvent> findAllFinishedSpecialEvents() {
        return specialEventDao.findAllFinishedSpecialEvents();
    }

    @Override
    public List<SpecialEvent> findAllGroupWinnerSpecialEvents() {
        List<SpecialEvent> allSpecialEvents = findAllSpecialEvents();

        return filterSpecialEvents(allSpecialEvents, true);
    }

    @Override
    public List<SpecialEvent> findAllNonGroupWinnerSpecialEvents() {
        List<SpecialEvent> allSpecialEvents = findAllSpecialEvents();

        return filterSpecialEvents(allSpecialEvents, false);
    }

    private List<SpecialEvent> filterSpecialEvents(
            List<SpecialEvent> allEvents, boolean isGroupsFilter) {
        List<SpecialEvent> filteredEvents = new ArrayList<SpecialEvent>();

        for (SpecialEvent specialEvent : allEvents) {
            if (specialEvent.getEventType().toString().toLowerCase()
                    .startsWith("group")) {
                if (isGroupsFilter) {
                    filteredEvents.add(specialEvent);
                }
            } else {
                if (!isGroupsFilter) {
                    filteredEvents.add(specialEvent);
                }
            }
        }

        return filteredEvents;
    }

    @Override
    public List<Match> findAllFinishedMatches() {
        return matchDao.findAllFinishedMatches();
    }

    @Override
    public List<Match> findMatchesByDate(int year, int month, int day) {
        validateDate(year, month, day);
        return matchDao.findMatchesByDate(year, month, day);
    }

    @Override
    public SpecialEvent updateSpecialEvent(SpecialEvent event) {
        validateEntity(event);
        return specialEventDao.updateSpecialEvent(event);
    }

    @Override
    public Match updateMatch(Match match) {
        validateEntity(match);
        return matchDao.updateMatch(match);
    }

    @Override
    public void deleteSpecialEvent(SpecialEvent specialEvent) {
        if (specialEvent != null) {
            specialEventDao.deleteSpecialEvent(specialEvent);
        }
    }

    @Override
    public void deleteMatch(Match match) {
        if (match != null) {
            matchDao.deleteMatch(match);
        }
    }

    @Override
    public Event stopPredictions(Event event) {
        event.setLocked(true);
        if (event instanceof Match) {
            return matchDao.updateMatch((Match) event);
        } else if (event instanceof SpecialEvent) {
            return specialEventDao.updateSpecialEvent((SpecialEvent) event);
        }

        return null;
    }
}
